library ieee;

use ieee.std_logic_1164.all;

use ieee.numeric_std.all;


entity dcacheSet is port(
  clk, nrst : in std_logic;
  tag_in    : in std_logic_vector(24 downto 0);
  data_in   : in std_logic_vector(63 downto 0);
  index_in  : in std_logic_vector(3 downto 0);


  recent_in : in std_logic;
  dirty_in  : in std_logic;

  recent_wen : in std_logic;
  data_wen   : in std_logic;

  data_out : out std_logic_vector(63 downto 0);
  tag_out  : out std_logic_vector(24 downto 0);
  hit      : out std_logic;
  dirty    : out std_logic;
  recent   : out std_logic);
end dcacheSet;



architecture data_cache of dcacheSet is
  type   ram is array(15 downto 0) of std_logic_vector(63 downto 0);
  type   tagg is array(15 downto 0) of std_logic_vector(24 downto 0);
  type   validd is array(15 downto 0) of std_logic;
  type   recentd is array(15 downto 0) of std_logic;
  type   dirtyd is array(15 downto 0) of std_logic;
  signal validd1, validd2 : validd;
  signal ram1, ram2       : ram;
  signal tagg1, tagg2     : tagg;
  signal recent1, recent2 : recentd;
  signal dirty1, dirty2   : dirtyd;

begin
  regg : process(clk, nrst)
  begin
    if nrst = '0' then
      for i in 0 to 15 loop
        validd1 (i) <= '0';
        dirty1(i)   <= '0';
        recent1(i) <= '0';
        ram1(i) <= (others =>'0');
        tagg1(i) <= (others =>'0');
      end loop;

    elsif falling_edge(clk) then
      for i in 0 to 15 loop
        validd1(i) <= validd2(i);
        dirty1(i)  <= dirty2(i);
        recent1(i) <= recent2(i);
        ram1 (i)   <= ram2(i);
        tagg1(i)   <= tagg2(i);
      end loop;

    end if;
  end process regg;

  nextstate : process(validd1, ram1, recent1, dirty1, tagg1, tag_in, data_in, dirty_in, data_wen, recent_in, recent_wen, index_in)
    variable var1 : integer range 0 to 15;
  begin
    
    var1 := to_integer(unsigned(index_in));
    for i in 0 to 15 loop
      tagg2(i)   <= tagg1(i);
      ram2(i)    <= ram1(i);
      validd2(i) <= validd1(i);
      recent2(i) <= recent1(i);
      dirty2(i)  <= dirty1(i);
    end loop;

    if data_wen = '1' then
      tagg2(var1)   <= tag_in;
      ram2(var1)    <= data_in;
      validd2(var1) <= '1';
      dirty2(var1)  <= dirty_in;
    end if;

    if recent_wen = '1' then
      recent2(var1) <= recent_in;
    end if;

    data_out <= ram1(var1);
    tag_out <= tagg1(var1);
    recent <= recent1(var1);
    dirty <= dirty1(var1);
    if tag_in = tagg1(var1) and validd1(var1) = '1' then
      hit <= '1';
    else
      hit <= '0';
    end if;
    
  end process nextstate;
end;

